home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 February: Tool Chest / Dev.CD Feb 97 TC.toast / Sample Code / Interapplication Communication / MenuScripter 4.0 / Sources / MSScript.c < prev    next >
Encoding:
Text File  |  1996-07-09  |  56.6 KB  |  2,138 lines  |  [TEXT/CWIE]

  1. // MSScript.c
  2. //
  3. // Original version by Jon Lansdell and Nigel Humphreys.
  4. // 4.0 and 3.1 updates by Greg Sutton.
  5. // Human Interface changes and GX Printing by Don Swatman
  6. // ©Apple Computer Inc 1996, all rights reserved.
  7.  
  8.  
  9. #include <Memory.h>
  10. #include <Resources.h>
  11. #include <TextEdit.h>
  12. #include <Controls.h>
  13. #include <Dialogs.h>
  14. #include <Errors.h>
  15. #include <Files.h>
  16. #include <Folders.h>
  17. #include <Components.h>
  18. #include <AppleEvents.h>
  19. #include <AppleScript.h>
  20. #include <AERegistry.h>
  21. #include <ASRegistry.h>
  22. #include <ASDebugging.h>
  23. #include <Processes.h>
  24.  
  25. #include "MSScript.h"
  26.  
  27. #include "MSUtils.h"
  28. #include "MSAEUtils.h"
  29. #include "MSAETextUtils.h"
  30. #include "MSAEMenuUtils.h"
  31. #include "MSWindow.h"
  32. #include "MSAESetData.h"
  33. #include "MSAEGetData.h"
  34. #include "MSResultWind.h"
  35. #include "MSAEDelete.h"
  36. #include "MSASSubroutines.h"
  37. #include "MSMain.h"
  38. #include "MSAEWindowUtils.h"
  39. #include "MSAERecording.h"
  40.  
  41. /*
  42.     Each menu (or menu item) can have a script associated with it. This
  43.     script has an ID equal to 32 * theMenuID + theItem number. A script
  44.     with an item number of 0 applies to the whole menu unless it is 
  45.     overridden by a particular script for an item in the menu.
  46.     
  47.     Scripts are stored in two resource types
  48.         'scpt' is a compiled script as returned by OSAStore()
  49.         'SCPT' is a raw text script as defined in the resource file
  50.         
  51.     At open application time scripts are built from the 'SCPT' resources 
  52.     if there are not any existing complied scripts of that resource ID.
  53.     These are stored in the preferences file for the application.
  54.     
  55.     One problem with the scripted menu commands is that if the application
  56.     name is changed the target is no longer found. This may be addressed later.
  57. */
  58.  
  59.  
  60.     // Constants
  61. #define kMaxScriptsInApp        100
  62. #define kCompiledScriptType        kOSAScriptResourceType
  63. #define kTextScriptType            'SCPT'
  64.  
  65. const short    kLaunchScriptID            = 128;
  66. const short    kApplicationScriptID    = 200;
  67. const short    kResultsScriptID        = 300;
  68. const short kPleaseWaitStart        = 1006;
  69. const short kPleaseWaitEnd            = 1007;
  70.  
  71. const short kEscapeKey                = 27;
  72. const short kEndOfTextKey            = 3;
  73.  
  74. const short    MenuScriptEditor        = 400;
  75.  
  76. const Str31    kPrefFileName            = "\pMenuScripter Prefs";
  77.  
  78.     // Prototypes
  79. pascal OSErr        MySendProc(const AppleEvent*    theAppleEvent,
  80.                                     AppleEvent*        reply,
  81.                                     AESendMode         sendMode,
  82.                                     AESendPriority     sendPriority,
  83.                                     long            timeOutInTicks,
  84.                                     AEIdleUPP        idleProc,
  85.                                     AEFilterUPP        filterProc,
  86.                                     long            refCon);
  87. pascal OSErr        StdActiveProc( long refCon );
  88.  
  89. static OSAID        GetScriptIDForResID( short lookForID );
  90. OSErr                OpenPreferencesResourceFile(short *theRefNum);
  91. OSErr                ClosePreferencesResourceFile( short theRefNum );
  92. void                AddMenuScript( short theResID, OSAID theScriptID, Boolean fChanged );
  93. OSErr                LoadApplicationScripts( void );
  94. OSErr                StoreApplicationScripts( void );
  95. OSErr                BuildMenuScripts( void );
  96. OSErr                StoreMenuScripts( void );
  97. Boolean                ScriptHasProperties( OSAID theScriptID );
  98. static void            SetUpUniversalProcedures( void );
  99. static DialogPtr    PoseWaitDialog( short theDialogID );
  100. void                DisplayErrorInScript( TEHandle theHTE );
  101.  
  102. pascal void            DrawGrowBoxItem( DialogPtr theDialog, short theItem );
  103. pascal void            DrawStyledTextEditRec( DialogPtr theDialog, short theItem );
  104. pascal void         DrawScrollBar( DialogPtr theDialog, short theItem );
  105. pascal void            ScrollVActionProc( ControlHandle control, short part );
  106. pascal Boolean        MyFilterProc( DialogPtr theDialog, EventRecord *myEvent, short *itemHit );
  107.  
  108. void                 MoveCustTextEditItem( DialogPtr theDialog, short theItem,
  109.                                                     short deltaW, short deltaH );
  110. void                 MoveScrollBarItem( DialogPtr theDialog, short theItem,
  111.                                                     short deltaW, short deltaH );
  112. void                 MoveOneDialogControlItem( DialogPtr theDialog, short theItem,
  113.                                                      short deltaW, short deltaH );
  114. void                 MoveOneDialogItem( DialogPtr theDialog, short theItem,
  115.                                                      short deltaW, short deltaH );
  116.  
  117.  
  118. void                 SetDrawProcForUserItem( DialogPtr theDialog,
  119.                                     short theItem, ControlActionUPP theProc );
  120. void                FlashButton( DialogPtr theDialog, short theItem );
  121. void                TrackTEPosn( ControlHandle theControl, TEHandle theHTE );
  122. void                SetScrollLimit( ControlHandle newScroll, TEHandle theHTE );
  123. Boolean                DoDialogMenu ( long menuResult, TEHandle theTE );
  124.  
  125. OSErr                SetMenuScript( short theResID, OSAID theScriptID );
  126. void                 SetMenuForDialog( void );
  127. void                 ReSetMenuForDialog( void );
  128.  
  129. pascal OSErr        EventPrehandler( AppleEvent *theEvent, AppleEvent *theReply, long theRefcon );
  130. Boolean                CanScriptEvent( AEEventClass theClass, AEEventID theID, AppleEvent* theEvent );
  131. void                AddMissingParameter( AEKeyword theAEKeyword, DescType theType,
  132.                                             Ptr theData, Size theDataSize, AppleEvent* theEvent );
  133. OSErr                DoScriptEvent( AppleEvent            *theEvent, 
  134.                                     AppleEvent            *theReply, 
  135.                                     OSAID                theScriptID );
  136. static OSErr        GetTokenDescScript( AEDesc* theTokenDesc, OSAID* theOSAID );
  137.  
  138.     // Globals
  139. extern short        gRefNum;
  140.  
  141. ComponentInstance    gScriptingComponent;
  142. short                gActiveMenuItem;
  143. OSASendUPP            oldSendProc;
  144. long                refCon;
  145. MenuScriptRecPtr    gMenuScripts;
  146. short                gNumScripts;
  147. short                gPrefsRefFile;
  148. OSAActiveUPP        gOSAActiveUPP;
  149. Boolean                gEditingScript; // Is the script editing dialog up?
  150.  
  151. ControlActionUPP    gScrollScriptVActionUPP;
  152. ControlActionUPP    gDrawStyledTextUPP;
  153. ControlActionUPP    gDrawScrollBarUPP;
  154. ControlActionUPP    gDrawGrowBoxUPP;
  155.  
  156.  
  157. //    These are used in documentation but not defined in the interfaces
  158.  
  159. #ifndef kComponentNotFound
  160.     #define kComponentNotFound    -1
  161. #endif
  162.  
  163.  
  164. pascal OSErr MySendProc(const AppleEvent*    theAppleEvent,
  165.                             AppleEvent*        reply,
  166.                             AESendMode         sendMode,
  167.                             AESendPriority     sendPriority,
  168.                             long            timeOutInTicks,
  169.                             AEIdleUPP        idleProc,
  170.                             AEFilterUPP        filterProc,
  171.                             long            refCon)
  172. #ifdef __MWERKS__
  173.     #pragma unused(refCon)
  174. #endif
  175.  
  176.     DescType     typeCode;
  177.     Size         descSize;
  178.     OSErr        myErr;
  179.     OSErr        ignoreErr;
  180.     OSType       whatEvent;
  181.     AppleEvent   myCopyAEvt;
  182.     
  183.     myErr = AEDuplicateDesc( theAppleEvent, &myCopyAEvt );
  184.  
  185.     myErr = AEGetAttributePtr(&myCopyAEvt, keyEventIDAttr, typeType, &typeCode, 
  186.                                     (Ptr)&whatEvent, sizeof(whatEvent), &descSize );
  187.                                                         
  188.     ignoreErr = AEDisposeDesc( &myCopyAEvt );
  189.     
  190.     if (myErr != noErr) whatEvent = 0x3F3F3F3F;
  191.     
  192.     //    Record the final Set Data that occurs due to a script
  193.     //    'gdte' = id sent to get 'aete' resource from app, dealt with
  194.     //    by system handler.
  195.  
  196.     if ( ( sendMode & kAEDontRecord ) && 
  197.             ( ( whatEvent != kAEGetData ) && ( whatEvent != kGetAETE ) ) )
  198.         sendMode = sendMode - kAEDontRecord;
  199.         
  200.     /* will be this when a5 bug fixed    // =Jon=
  201.     return((*oldSendProc)(theAppleEvent,
  202.                                  reply,
  203.                                  sendMode,
  204.                                  sendPriority,
  205.                                  timeOutInTicks,
  206.                                  idleProc,
  207.                                  filterProc,
  208.                                  refCon));
  209.     */
  210.     
  211.     return( AESend( theAppleEvent, reply, sendMode, sendPriority,
  212.                                 timeOutInTicks, idleProc, filterProc ) );                            
  213. }    // MySendProc
  214.  
  215.  
  216. // Our activeProc is called at various times during script execution and compilation
  217. // we use this to detect when the application is being sent to the background. This can happen
  218. // when a script is targetted to another application, causing this application to be
  219. // brought to the front. Since HiliteMenu(0) is called when the menu command has completed - and
  220. // this will be called when the script has completed, we must ensure that the application is
  221. // in the foreground when HiliteMenu is called. Otherwise the menu bar gets drawn over the frontmost
  222. // application, which is not what we want.
  223.  
  224. pascal OSErr StdActiveProc( long refCon )
  225. {
  226. #ifdef __MWERKS__
  227.     #pragma unused(refCon)
  228. #endif
  229.  
  230.       // Call WaitnextEvent() to get suspend event
  231.     EventRecord myEvent;
  232.  
  233.     if ( ! gEditingScript )
  234.     {
  235.         if ( WaitNextEvent( everyEvent, &myEvent, 0, NULL ) )
  236.         {
  237.             switch ( myEvent.what )
  238.             {
  239.                 case osEvt:
  240.                     HiliteMenu( 0 );// Don't call HiliteMenu in the background 
  241.                                     // so clear it before we switch to the background
  242.                     
  243.                     if ( ( myEvent.message >> 24 ) & suspendResumeMessage )    // suspend or resume
  244.                     {
  245.                         gInBackground = ( ( myEvent.message & resumeFlag ) == 0);
  246.                         DoActivate( FrontWindow( ), ! gInBackground );
  247.                     }
  248.                     break;
  249.             }
  250.         }
  251.     }
  252.  
  253.         // Now call the standard ActiveProc
  254.     return ( CallOSAActiveProc( gOSAActiveUPP,0 ) );
  255. }
  256.  
  257.     
  258. static OSAID    GetScriptIDForResID( short lookForID )
  259. {
  260.     short    index;
  261.     
  262.     for ( index = 0; index < gNumScripts; index++ )
  263.     {
  264.         if ( gMenuScripts[index].theResID == lookForID )
  265.             return gMenuScripts[index].theScriptID;
  266.     }
  267.         
  268.     return kOSANullScript;
  269. }
  270.     
  271. MenuScriptRecPtr    GetMenuScriptRecPtr( short theResID )
  272. {
  273.     short    index;
  274.     
  275.     for ( index = 0; index < gNumScripts; index++ )
  276.     {
  277.         if ( gMenuScripts[index].theResID == theResID )
  278.             return &gMenuScripts[index];
  279.     }
  280.         
  281.     return NULL;
  282. }
  283.     
  284.  
  285. //    Name : OpenPreferencesResourceFile
  286. //    Purpose : Opens the prefs file, in the system prefs folder
  287. //                creating it if it is not found. Sets the current
  288. //                resource file to the prefs file so that resources
  289. //                will be read from there in preference to the app
  290. //                if they have been overridden, and new resources
  291. //                will be created in it.
  292.     
  293. OSErr    OpenPreferencesResourceFile(short *theRefNum)
  294. {
  295.     short  foundVRefNum;
  296.     long   foundDirID;
  297.     OSErr  myErr;
  298.     
  299.     myErr = FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder,
  300.                                                      &foundVRefNum, &foundDirID);
  301.                                          
  302.     if (myErr==noErr)
  303.     {
  304.  
  305.         *theRefNum = HOpenResFile(foundVRefNum, foundDirID, kPrefFileName, fsWrPerm);
  306.         myErr = ResError();
  307.         
  308.         if (myErr==fnfErr)
  309.         {
  310.             HCreateResFile(foundVRefNum, foundDirID, kPrefFileName);
  311.             myErr = ResError();
  312.  
  313.             *theRefNum = HOpenResFile(foundVRefNum, foundDirID, kPrefFileName, fsWrPerm);
  314.             myErr = ResError();
  315.         }
  316.     }
  317.  
  318.     return(myErr);
  319. }
  320.     
  321. OSErr    ClosePreferencesResourceFile( short theRefNum )
  322. {
  323.     CloseResFile( theRefNum );
  324.     return( ResError( ) );
  325. }
  326.  
  327.  
  328. //    Name : AddMenuScript
  329. //    Purpose : Adds a compiled script OSAID into the
  330. //              global gMenuScripts array for later access
  331.  
  332. void    AddMenuScript( short theResID, OSAID theScriptID, Boolean fChanged )
  333. {
  334.     if ( gNumScripts < kMaxScriptsInApp )
  335.     {
  336.         gMenuScripts[gNumScripts].theResID = theResID;
  337.         gMenuScripts[gNumScripts].theScriptID = theScriptID;
  338.         gMenuScripts[gNumScripts].fChanged = fChanged;
  339.         gNumScripts++;
  340.         
  341.         (void)CheckForMenuItemName( theResID, theScriptID );
  342.     }
  343. }
  344.  
  345.  
  346. //    Name : BuildMenuScripts
  347. //    Purpose : Reads compiled scripts from the prefs file,
  348. //              Any uncompiled scripts ('SCPT' resources with
  349. //               no 'scpt' of same id are compiled. Any which fail
  350. //               to compile are ignored. Changed scripts are stored
  351. //               in the preferences file on quit.
  352.  
  353. OSErr    BuildMenuScripts( void )
  354. {
  355.     short        aScriptCount,
  356.                 index,
  357.                 anID;
  358.     ResType     aResType;
  359.     Str255        aResName;
  360.     Handle        aScript;
  361.     AEDesc        aScriptDesc = { typeNull, NULL };
  362.     OSAID        aScriptID = kOSANullScript;
  363.     OSErr        anErr;
  364.     
  365.     gNumScripts = 0;
  366.     
  367.     gMenuScripts = (MenuScriptRecord *)NewPtr( sizeof( MenuScriptRecord ) * kMaxScriptsInApp );
  368.     
  369.         // Firstly load all the 'scpt' scripts stored in the preferences file,
  370.         //  these scripts may be customised by the user.
  371.     aScriptCount = Count1Resources( kCompiledScriptType );
  372.     for ( index = 1 ; index <= aScriptCount ; index++ )
  373.     {
  374.         aScript = Get1IndResource( kCompiledScriptType, index );
  375.         GetResInfo( aScript, &anID, &aResType, aResName );
  376.         anErr = ResError( );
  377.         if ( noErr != anErr ) goto done;
  378.         
  379.         HLock( aScript );
  380.         anErr = AECreateDesc( typeOSAGenericStorage, (Ptr)*aScript,
  381.                                     GetHandleSize( aScript ), &aScriptDesc );
  382.         HUnlock( aScript );
  383.         ReleaseResource( aScript );
  384.         if ( noErr != anErr ) goto done;    // This shouldn't happen
  385.         
  386.         aScriptID = kOSANullScript;
  387.         anErr = OSALoad( gScriptingComponent, &aScriptDesc, kOSAModeNull, &aScriptID );
  388.         
  389.         if ( noErr == anErr )
  390.             AddMenuScript( anID, aScriptID, false );
  391.         
  392.         (void)AEDisposeDesc( &aScriptDesc );
  393.     }
  394.         
  395.         // Next load and compile any of the text based scripts, 'SCPT', that 
  396.         //  have no equivalent 'scpt' in the preferences file.
  397.     aScriptCount = CountResources( kTextScriptType );
  398.     for ( index = 1; index <= aScriptCount; index++ )
  399.     {
  400.         aScript = GetIndResource( kTextScriptType, index );
  401.         GetResInfo( aScript, &anID, &aResType, aResName );
  402.         anErr = ResError( );
  403.         if ( noErr != anErr ) goto done;
  404.         
  405.         if ( GetScriptIDForResID( anID ) == kOSANullScript )
  406.         {
  407.                     // Stored as a C string so knock off NULL terninator
  408.             HLock( aScript );
  409.             anErr = AECreateDesc( typeChar, (Ptr)*aScript,
  410.                                     GetHandleSize( aScript ) - 1, &aScriptDesc );
  411.             HUnlock( aScript );
  412.             ReleaseResource( aScript );
  413.             if ( noErr != anErr ) goto done;    // This shouldn't happen
  414.             
  415.             aScriptID = kOSANullScript;
  416.             anErr = OSACompile( gScriptingComponent, &aScriptDesc,
  417.                                     kOSAModeCompileIntoContext, &aScriptID );
  418.                                                 
  419.             if ( noErr == anErr )
  420.                 AddMenuScript( anID, aScriptID, true );    // We need to save this script
  421.                                                         //  so set fChanged to true.
  422.             (void)AEDisposeDesc( &aScriptDesc );
  423.         }
  424.     }
  425.     
  426. done:
  427.     return anErr;
  428. }
  429.  
  430. // This checks to see if a script contains
  431. //  properties. These could change in the script and therefore
  432. //  the script needs to be stored for the next
  433. //  time the application is launched.
  434.  
  435. Boolean    ScriptHasProperties( OSAID theScriptID )
  436. {
  437.     AEDescList    resultingPropertyNames = { typeNull, NULL };
  438.     long        aCount = 0;
  439.     OSErr        anErr;
  440.     Boolean        aResult = true;
  441.  
  442.         // OSAGetPropertyNames() returns typeChar descriptors of
  443.         //  all the properties in a script.
  444.     anErr = OSAGetPropertyNames( gScriptingComponent, kOSAModeNull, 
  445.                         theScriptID, &resultingPropertyNames );
  446.  
  447.     if ( noErr != anErr )
  448.     {
  449.         aResult = false;
  450.         goto done;
  451.     }
  452.     
  453.     anErr = AECountItems( &resultingPropertyNames, &aCount );
  454.     
  455.     if ( noErr != anErr || aCount == 0 )
  456.         aResult = false;
  457.     
  458. done:
  459.     (void)AEDisposeDesc( &resultingPropertyNames );
  460.  
  461.     return aResult;
  462. }
  463.  
  464. OSErr    StoreMenuScripts( void )
  465. {
  466.     short        index;
  467.     OSErr        anErr;
  468.     
  469.     for ( index = 0; index < gNumScripts; index++ )
  470.     {
  471.             // If there are properties or it
  472.             //  has changed then store the script
  473.         if ( gMenuScripts[index].fChanged
  474.                 || ScriptHasProperties( gMenuScripts[index].theScriptID ) )
  475.         {
  476.             anErr = StoreScriptToResFileRef( gPrefsRefFile, gMenuScripts[index].theResID,
  477.                                                         gMenuScripts[index].theScriptID, "\p" );
  478.         }
  479.     }
  480.         
  481.     return anErr;
  482. }
  483.  
  484.  
  485. OSErr    LoadApplicationScripts( void )
  486. {
  487.     OSAID    aScriptID = kOSANullScript,
  488.             aResultID = kOSANullScript;
  489.     DPtr    aDoc;
  490.     OSErr    anErr;
  491.  
  492.     OpenPreferencesResourceFile( &gPrefsRefFile );
  493.     
  494.     gMenuScripts = NULL;
  495.     anErr = BuildMenuScripts( );
  496.     if ( noErr != anErr ) goto done;
  497.     
  498.         // Get the current application scipt from the prefs file.
  499.         //  If there isn't one then the launch script can set one.
  500.     anErr = LoadScriptFromResFileRef( gPrefsRefFile,
  501.                             kApplicationScriptID, &gAppRec.theScriptID );
  502.         
  503.         // Load the results window script too.        
  504.     aDoc = GetResultsDoc( );
  505.     if ( aDoc )
  506.         anErr = LoadScriptFromResFileRef( gPrefsRefFile,
  507.                             kResultsScriptID, &aDoc->theScriptID );
  508.     
  509.         // The application script property is set by executing the 
  510.         //  application script - current script checks to see
  511.         //  if there is already a script - from prefs file.
  512.     anErr = LoadScriptFromResFileRef( gRefNum, kLaunchScriptID, &aScriptID );
  513.     if ( noErr != anErr ) goto done;
  514.     
  515.     anErr = OSAExecute( gScriptingComponent, aScriptID, kOSANullScript,
  516.                                             kOSAModeAlwaysInteract, &aResultID );
  517.     
  518. done:
  519.     (void)OSADispose( gScriptingComponent, aScriptID );
  520.     (void)OSADispose( gScriptingComponent, aResultID );
  521.         
  522.     return anErr;
  523. }
  524.  
  525.  
  526. OSErr    StoreApplicationScripts( void )
  527. {
  528.     DPtr    aDoc;
  529.     OSErr    anErr;
  530.     
  531.     anErr = StoreMenuScripts( );
  532.     if ( noErr != anErr ) goto done;
  533.  
  534.         // Store any changes to the applications script
  535.     anErr = StoreScriptToResFileRef( gPrefsRefFile, kApplicationScriptID,
  536.                                 gAppRec.theScriptID, "\pApplicationScript" );
  537.  
  538.         // Store any changes to the results document script
  539.     aDoc = GetResultsDoc( );
  540.     if ( aDoc )
  541.         anErr = StoreScriptToResFileRef( gPrefsRefFile, kResultsScriptID,
  542.                                 aDoc->theScriptID, "\pResultsScript" );
  543.  
  544.     ClosePreferencesResourceFile( gPrefsRefFile );
  545.  
  546. done:
  547.     return anErr;
  548. }
  549.  
  550.  
  551. static void    SetUpUniversalProcedures( void )
  552. {
  553.     gScrollScriptVActionUPP = NewControlActionProc( ScrollVActionProc );
  554.     gDrawStyledTextUPP = NewControlActionProc( DrawStyledTextEditRec );
  555.     gDrawScrollBarUPP = NewControlActionProc( DrawScrollBar );
  556.     gDrawGrowBoxUPP = NewControlActionProc( DrawGrowBoxItem );
  557. }
  558.  
  559.  
  560. static DialogPtr    PoseWaitDialog( short theDialogID )
  561. {
  562.     DialogPtr progressDialog;
  563.  
  564.         // pose a dialog indicating that we are connecting
  565.         // to the AppleScript component.
  566.     progressDialog = GetNewDialog( theDialogID, NULL, (WindowPtr)-1 );
  567.     SetPort( progressDialog );
  568.     DrawDialog( progressDialog );
  569.     return progressDialog;
  570. }
  571.  
  572. //    Name:   InitEditorScripting
  573. //    Purpose:Connects to the AppleScript component.
  574.  
  575. OSErr    InitEditorScripting( void )
  576. {
  577.     GrafPtr                 oldPort;
  578.     DialogPtr                progressDialog;
  579.     OSAError                 err = 0;
  580.     ComponentDescription     descr;
  581.     Component               aComponent;
  582.     ComponentInstance         aScriptingComponent;
  583.     
  584.     GetPort( &oldPort );
  585.     progressDialog = PoseWaitDialog( kPleaseWaitStart );
  586.     
  587.     SetUpUniversalProcedures( );
  588.     gEditingScript = false;
  589.     
  590.     descr.componentType         = kOSAComponentType;
  591.     descr.componentSubType      = (OSType) 0;
  592.     descr.componentManufacturer = (OSType) 0;
  593.     descr.componentFlags        = kOSASupportsCompiling + 
  594.                                        kOSASupportsGetSource +
  595.                                            kOSASupportsAECoercion + 
  596.                                             kOSASupportsAESending +
  597.                                                 kOSASupportsRecording +
  598.                                                     kOSASupportsConvenience +
  599.                                                         kOSASupportsEventHandling;
  600.     descr.componentFlagsMask    = descr.componentFlags;
  601.     
  602.     aComponent = FindNextComponent( NULL, &descr );
  603.         
  604.     if ( ! aComponent )
  605.     {
  606.         err = kComponentNotFound;
  607.         goto done;
  608.     }
  609.     else
  610.     {
  611.         aScriptingComponent = OpenComponent( aComponent );
  612.                                                                                                 
  613.         if (! aScriptingComponent)
  614.         {
  615.             err = kComponentNotFound;
  616.             goto done;
  617.         }
  618.     }
  619.         
  620.     gScriptingComponent = aScriptingComponent;
  621.  
  622.             
  623.     err = OSAGetSendProc( gScriptingComponent, &oldSendProc, &refCon );
  624.     if ( noErr != err ) goto done;
  625.                                                 
  626.     err = OSASetSendProc( gScriptingComponent, NewOSASendProc( MySendProc ), 0 );
  627.     if ( noErr != err ) goto done;
  628.  
  629.     err = AEInstallSpecialHandler( keyPreDispatch, (UniversalProcPtr)NewAEEventHandlerProc( EventPrehandler ), false );
  630.     if ( noErr != err ) goto done;
  631.     
  632.     err = LoadApplicationScripts( );
  633.  
  634. done:
  635.     DisposeDialog( progressDialog );
  636.     SetPort( oldPort );
  637.  
  638.     return err;
  639. }
  640.  
  641.  
  642. OSErr    SetOSAActiveProcedure(void)
  643. {
  644.     OSErr    err;
  645.     long    theRefCon;
  646.     
  647.         // store the old active proc in order to call this from ours
  648.     err = OSAGetActiveProc( gScriptingComponent, &gOSAActiveUPP, &theRefCon );
  649.     
  650.     return( OSASetActiveProc( gScriptingComponent, NewOSAActiveProc( StdActiveProc ), 0 ) );
  651. }
  652.  
  653.  
  654. //    Name    : CloseEditorScripting
  655. //    Purpose : Shutdown of editor scripting capabilities
  656.  
  657. OSErr    CloseEditorScripting( void )
  658. {
  659.     GrafPtr        oldPort;
  660.     DialogPtr    progressDialog;
  661.     short        index;
  662.     OSErr        err;
  663.     
  664.     GetPort( &oldPort );
  665.     progressDialog = PoseWaitDialog( kPleaseWaitEnd );
  666.  
  667.     StoreApplicationScripts( );
  668.     
  669.     for ( index = 0; index < gNumScripts; index++ )
  670.         err = OSADispose( gScriptingComponent, gMenuScripts[index].theScriptID );
  671.     
  672.     err = CloseComponent( gScriptingComponent );
  673.  
  674.     DisposeDialog( progressDialog );
  675.     SetPort( oldPort );
  676.     
  677.     return err;
  678. }
  679.  
  680.     
  681.  
  682. //    Name:    DisplayErrorInScript
  683. //    Purpose: Put up an alert showing the error text for the last error.
  684. //             Also selects the responsible text in theHTE if one is supplied
  685.  
  686. void    DisplayErrorInScript( TEHandle theHTE )
  687. {
  688.     Str255   errorMessageText;
  689.     AEDesc   errRangeDesc;
  690.     AEDesc   errRecordDesc;
  691.     AEDesc   errTextDesc;
  692.     AEDesc   errNumberDesc;
  693.     DescType typeCode;
  694.     Size     actSize;
  695.     OSErr    myErr;
  696.     OSErr    ignoreErr;
  697.     OSErr    errorNumber;
  698.     short    errorStart;
  699.     short    errorEnd;
  700.     
  701.     SetCursor(&qd.arrow);
  702.     
  703.     myErr = OSAScriptError(gScriptingComponent, kOSAErrorNumber,
  704.                                         typeShortInteger, &errNumberDesc);
  705.     
  706.     myErr = GetIntegerFromDescriptor(&errNumberDesc, &errorNumber);
  707.             
  708.     ignoreErr = AEDisposeDesc(&errNumberDesc);
  709.     
  710.     myErr = OSAScriptError(gScriptingComponent, kOSAErrorMessage,
  711.                                                 typeChar, &errTextDesc);
  712.                                                  
  713.     myErr = GetPStringFromDescriptor( &errTextDesc, errorMessageText );
  714.     
  715.     ignoreErr = AEDisposeDesc(&errTextDesc);
  716.     
  717.     if (theHTE)
  718.     {
  719.         myErr = OSAScriptError(gScriptingComponent, kOSAErrorRange,
  720.                                         typeOSAErrorRange, &errRangeDesc);
  721.                                                      
  722.         myErr = AECoerceDesc(&errRangeDesc, typeAERecord, &errRecordDesc);
  723.         
  724.         ignoreErr = AEDisposeDesc(&errRangeDesc);
  725.         
  726.         myErr = AEGetKeyPtr(&errRecordDesc, keyOSASourceStart, typeShortInteger,
  727.                             &typeCode, (Ptr)&errorStart, sizeof(errorStart), &actSize);
  728.                                                 
  729.         myErr = AEGetKeyPtr(&errRecordDesc, keyOSASourceEnd, typeShortInteger,
  730.                                 &typeCode, (Ptr)&errorEnd, sizeof(errorEnd), &actSize);
  731.                                                 
  732.         ignoreErr = AEDisposeDesc(&errRecordDesc);
  733.         
  734.         TESetSelect(errorStart, errorEnd, theHTE);
  735.     }
  736.     
  737.     ShowError(errorMessageText, errorNumber);
  738. }
  739.  
  740.  
  741. //    Name    : CompileDocument
  742. //    Purpose : Compiles the text of the supplied document - does NOT keep
  743. //              a compiled version - merely checks that it will compile for now
  744.  
  745. OSErr    CompileDocument( DPtr theDoc )
  746. {
  747.     WindowPropToken    aToken;
  748.     AEDesc            aTextDesc = { typeNull, NULL },
  749.                     aCompiledDesc = { typeNull, NULL },
  750.                     aNullDesc = { typeNull, NULL };
  751.     OSAID            aScriptID = kOSANullScript;
  752.     OSErr            anErr;
  753.     
  754.     aToken.tokenWindowToken.tokenWindow = theDoc->theWindow;
  755.     aToken.tokenProperty = pText;        // All of the text in document
  756.     anErr = GetDocumentTokenProperty( &aToken, typeWildCard, &aTextDesc );
  757.     if ( noErr != anErr ) goto done;
  758.         
  759.     anErr = OSACompile( gScriptingComponent, &aTextDesc,
  760.                                             kOSAModeCompileIntoContext, &aScriptID );
  761.     if ( noErr != anErr ) goto done;
  762.         
  763.     anErr = OSAGetSource( gScriptingComponent, aScriptID,
  764.                                         typeStyledText, &aCompiledDesc );
  765.     if ( noErr != anErr ) goto done;
  766.     
  767.     anErr = DisplayDescResult( theDoc->theWindow, &aCompiledDesc, NULL, noErr );
  768.  
  769. done:
  770.     (void)DisplayDescResult( GetResultsWindPtr( ), &aNullDesc, theDoc, anErr );
  771.  
  772.     (void)OSADispose( gScriptingComponent, aScriptID );
  773.     (void)AEDisposeDesc( &aTextDesc );
  774.     (void)AEDisposeDesc( &aCompiledDesc );
  775.  
  776.     return anErr;
  777. }
  778.     
  779.  
  780. //    Name    : ExecuteDocument
  781. //    Purpose : Compiles the text of the supplied document and then executes it
  782. //              - does NOT keep a compiled version after execution
  783.  
  784. OSErr    ExecuteDocument( DPtr theDoc )
  785. {
  786.     WindowPropToken    aToken;
  787.     AEDesc            aTextDesc = { typeNull, NULL },
  788.                     aCompiledDesc = { typeNull, NULL };
  789.     OSAID            aScriptID = kOSANullScript,
  790.                     aResultID = kOSANullScript;
  791.     OSErr            anErr;
  792.     
  793.     aToken.tokenWindowToken.tokenWindow = theDoc->theWindow;
  794.     aToken.tokenProperty = pText;        // All of the text in document
  795.     anErr = GetDocumentTokenProperty( &aToken, typeWildCard, &aTextDesc );
  796.     if ( noErr != anErr ) goto done;
  797.     
  798.     anErr = OSACompile( gScriptingComponent, &aTextDesc, kOSAModeCompileIntoContext, &aScriptID );
  799.     if ( noErr != anErr ) goto done;
  800.                 
  801.             // Set the compiled text first, before executing
  802.     anErr = OSAGetSource( gScriptingComponent, aScriptID,
  803.                                     typeStyledText, &aCompiledDesc );
  804.     if ( noErr != anErr ) goto done;
  805.                                     
  806.     anErr = DisplayDescResult( theDoc->theWindow, &aCompiledDesc, NULL, noErr );
  807.     if ( noErr != anErr ) goto done;
  808.     
  809.     anErr = OSAExecute( gScriptingComponent, aScriptID,
  810.                             kOSANullScript, kOSAModeNull, &aResultID );
  811.  
  812. done:
  813.         // If aResultID is kOSANullScript then clear the window
  814.     (void)DisplayOSAIDResult( GetResultsWindPtr( ), aResultID, theDoc, anErr );
  815.  
  816.     (void)OSADispose( gScriptingComponent, aScriptID );
  817.     (void)OSADispose( gScriptingComponent, aResultID );
  818.     (void)AEDisposeDesc( &aTextDesc );
  819.     (void)AEDisposeDesc( &aCompiledDesc );
  820.  
  821.     return anErr;
  822. }
  823.  
  824.  
  825. //    Name   : ScriptForMenuExists
  826. //    Purpose: Tests for the existance of a valid script for a given menu item             
  827.     
  828. OSErr    ScriptForMenuExists(short theMenu, short theItem, Boolean *exists)
  829. {
  830.     short  resID;
  831.     OSAID  myScriptID;
  832.     OSErr  myErr;
  833.     
  834.     myErr = noErr;
  835.     
  836.     resID = (theMenu<<5) + theItem;
  837.     
  838.     myScriptID = GetScriptIDForResID(resID);
  839.     
  840.     if (myScriptID==kOSANullScript)
  841.     {
  842.         if (theItem!=0)
  843.             myErr = ScriptForMenuExists(theMenu, 0, exists);
  844.         else
  845.             *exists = false;
  846.     }
  847.     else
  848.       *exists = true;
  849.             
  850.     return myErr;        
  851. } // ScriptForMenuExists
  852.     
  853.     
  854. //    Name   : ExecuteScriptForMenu
  855. //    Purpose: Executes a script associated with the menu item.
  856. //             Should be called only after ScriptForMenuExists
  857. //                returns exists.
  858.  
  859. OSErr    ExecuteScriptForMenu( short theMenu, short theItem )
  860. {
  861.     short            resID;
  862.     OSAID            aScriptID,
  863.                     aResultID = kOSANullScript;
  864.     OSErr            err;
  865.  
  866.     resID = ( theMenu << 5 ) + theItem;
  867.     
  868.     aScriptID = GetScriptIDForResID( resID );
  869.             
  870.     if ( aScriptID == kOSANullScript )
  871.     {
  872.         resID = ( theMenu << 5 ); // look for a script for the whole menu - item 0
  873.         aScriptID = GetScriptIDForResID( resID );
  874.     }
  875.     
  876.     if ( aScriptID != kOSANullScript )
  877.     {
  878.         gActiveMenuItem = theItem;
  879.         
  880.         err = OSAExecute( gScriptingComponent, aScriptID,
  881.                                     kOSANullScript, 0, &aResultID );
  882.  
  883.         (void)DisplayOSAIDResult( GetResultsWindPtr( ), aResultID, NULL, err );
  884.  
  885.         gActiveMenuItem = 0;
  886.     }
  887.  
  888. done:
  889.     (void)OSADispose( gScriptingComponent, aResultID );
  890.     
  891.     return err;
  892. }
  893.  
  894.  
  895. //    Name :   GetScriptActiveItem
  896. //    Purpose : Used by SVAppleEvents for the active item property of a menu.
  897. //              Allows a script associated with more than one menu item to
  898. //                find which menu item it was called by.
  899.  
  900. short    GetScriptActiveItem( void )
  901. {
  902.     return gActiveMenuItem;
  903. }
  904.  
  905.  
  906.  
  907. //    Routines used in the StyledTextEdit Dialog Item
  908.  
  909. struct StyleTextInfo
  910. {
  911.     ControlHandle theScrollBar;
  912.     TEHandle      theTEHandle;
  913. };
  914. typedef struct StyleTextInfo StyleTextInfo;
  915. typedef StyleTextInfo *pStyleTextInfo;
  916.  
  917.  
  918. pascal void DrawGrowBoxItem( DialogPtr theDialog, short theItem )
  919. {
  920.     short   theType;
  921.     Handle  theHandle;
  922.     Rect    itemRect;
  923.             
  924.     GetDItem(theDialog, theItem, &theType, &theHandle, &itemRect);
  925.     PlotIconID (&itemRect, atBottomRight, ttNone, 400);
  926. }
  927.  
  928. pascal void DrawStyledTextEditRec( DialogPtr theDialog, short theItem )
  929. {
  930.     short   theType;
  931.     Handle  theHandle;
  932.     Rect    itemRect;
  933.             
  934.     GetDItem(theDialog, theItem, &theType, &theHandle, &itemRect);
  935.     FrameRect(&itemRect);
  936.     InsetRect(&itemRect, 5, 5);
  937.     
  938.     TEUpdate(&itemRect, ((pStyleTextInfo) GetWRefCon(theDialog))->theTEHandle);
  939. }
  940.     
  941. pascal void DrawScrollBar( DialogPtr theDialog, short theItem )
  942. {        
  943. #ifdef __MWERKS__
  944.     #pragma unused(theItem)
  945. #endif
  946.  
  947.     Draw1Control(((pStyleTextInfo) GetWRefCon(theDialog))->theScrollBar);
  948. }
  949.  
  950.  
  951. //    Name:    SetDrawProcForUserItem
  952. //    Purpose: Installs a procedure that will be called when theItem needs
  953. //             to be drawn.
  954.  
  955. void SetDrawProcForUserItem( DialogPtr theDialog, short theItem, ControlActionUPP theProc )
  956. {
  957.     short  theType;
  958.     Handle theHandle;
  959.     Rect   itemRect;
  960.     
  961.     GetDItem(theDialog, theItem, &theType, &theHandle, &itemRect);
  962.     SetDItem(theDialog, theItem, theType, (Handle)theProc, &itemRect);
  963. }
  964.     
  965.  
  966. //    Name:    FlashButton
  967. //    Purpose: Provide visual effect of button having been
  968. //             selected.
  969.  
  970. void    FlashButton( DialogPtr theDialog, short theItem )
  971. {
  972.     short    theType;
  973.     Handle   theHandle;
  974.     Rect     itemRect;
  975.     
  976.     GetDItem(theDialog, theItem, &theType, &theHandle, &itemRect);
  977.     
  978.     HiliteControl((ControlHandle)theHandle, inButton);
  979.     HiliteControl((ControlHandle)theHandle, 0);
  980. }
  981.     
  982.  
  983. //    Name:    ScrollVActionProc
  984. //    Purpose: Called as scrollbar is tracked in buttons or page up/down.
  985. //             Keeps text in sync with scrollBar
  986.  
  987. pascal void ScrollVActionProc( ControlHandle control, short part )
  988. {
  989.     short  amount;
  990.     short  initialValue;
  991.     
  992.     if ( part )
  993.     {
  994.         switch ( part )
  995.         {
  996.             case inUpButton:
  997.             case inDownButton:
  998.                 amount = 24;
  999.                 break;
  1000.             case inPageUp:
  1001.             case inPageDown:
  1002.                 amount = (**control).contrlRect.bottom - (**control).contrlRect.top;
  1003.                 break;
  1004.         }
  1005.         
  1006.         if ( part == inUpButton || part == inPageUp )
  1007.             amount = -amount; // reverse direction
  1008.     
  1009.         initialValue = GetCtlValue( control );
  1010.     
  1011.         SetCtlValue( control, initialValue+amount ); // Pinned within Min/Max automatically
  1012.         
  1013.         amount = GetCtlValue( control ) - initialValue;                
  1014.         
  1015.         if (amount)
  1016.             TEScroll(0, -amount,
  1017.                 ((pStyleTextInfo)GetWRefCon((**control).contrlOwner))->theTEHandle);
  1018.     }
  1019. } // ScrollVActionProc
  1020.     
  1021.  
  1022. //    Name:    TrackTEPosn
  1023. //    Purpose: Ensures that the scrollbar value matches the position
  1024. //             of the text edit record.
  1025.  
  1026. void    TrackTEPosn( ControlHandle theControl, TEHandle theHTE )
  1027. {
  1028.     short shouldBe;
  1029.     
  1030.     shouldBe = (**theHTE).viewRect.top - (**theHTE).destRect.top;
  1031.                         
  1032.     if ( GetCtlValue( theControl ) != shouldBe )
  1033.         SetCtlValue( theControl, shouldBe );
  1034. }
  1035.  
  1036.  
  1037. //    Name:    SetScrollLimit
  1038. //    Purpose: Ensures that the maximum value of the scrollbar is sufficient
  1039. //             to allow showing of all text, and no more.
  1040.  
  1041. void    SetScrollLimit( ControlHandle newScroll, TEHandle theHTE )
  1042. {
  1043.     Point     teLimit;
  1044.     short     currentMax;
  1045.     short     currentValue;
  1046.     TextStyle theStyle;
  1047.     short     lineHeight;
  1048.     short     fontAscent;
  1049.     
  1050.     currentMax = GetCtlMax(newScroll);
  1051.     
  1052.     //    Scroll max should be position of bottom of bottom line when unscrolled
  1053.     //    This is equal to
  1054.     //      The position of the bottom line relative to current position +
  1055.     //        The amount currently scrolled -
  1056.     //        The height of the visible part
  1057.             
  1058.     teLimit    = TEGetPoint((**theHTE).teLength, theHTE); // Position of bottom relative to current posn
  1059.     
  1060.     TEGetStyle((**theHTE).teLength, &theStyle, &lineHeight, &fontAscent,theHTE);        
  1061.     teLimit.v += lineHeight-fontAscent; // Add in for descent - TEGetPoint is posn of baseline not bottom of chars
  1062.     
  1063.     teLimit.v += ((**theHTE).viewRect.top -(**theHTE).destRect.top); // Amount already scrolled
  1064.     
  1065.     teLimit.v -= ((**theHTE).viewRect.bottom - (**theHTE).viewRect.top); // Height of page
  1066.     
  1067.     if (teLimit.v<0) // Cannot be negative
  1068.         teLimit.v = 0;
  1069.         
  1070.     if ( currentMax > teLimit.v )
  1071.     {
  1072.         currentValue = GetCtlValue( newScroll );
  1073.  
  1074.         if ( currentValue > teLimit.v )
  1075.         {
  1076.             TEScroll( 0, currentValue - teLimit.v, theHTE );
  1077.             SetCtlValue( newScroll, teLimit.v );
  1078.         }
  1079.  
  1080.         SetCtlMax( newScroll, teLimit.v );
  1081.     }
  1082.         
  1083.     if ( currentMax < teLimit.v )
  1084.         SetCtlMax( newScroll, teLimit.v );
  1085. }
  1086.  
  1087. #define kCompile   3
  1088. #define kTextItem  4
  1089. #define kScrollBar 5
  1090. #define kGrowBox   6
  1091.  
  1092. Boolean DoDialogMenu( long menuResult, TEHandle theTE )
  1093. {
  1094.     short   theItem;
  1095.     short   theMenuID;
  1096.     Boolean hasHandled = false;
  1097.  
  1098.     theItem     = LoWord( menuResult );
  1099.     theMenuID = HiWord( menuResult );
  1100.  
  1101.     switch ( theMenuID )
  1102.     {
  1103.         case editID:
  1104.             switch (theItem)
  1105.             {
  1106.                 case cutCommand:
  1107.                     TECut ( theTE );
  1108.                     hasHandled = true;
  1109.                     break;
  1110.                                              
  1111.                 case copyCommand:
  1112.                     TECopy ( theTE );
  1113.                     hasHandled = true;
  1114.                     break;
  1115.                                              
  1116.                 case pasteCommand:
  1117.                 {
  1118.                     TEStylePaste ( theTE );
  1119.                     hasHandled = true;
  1120.                     break;
  1121.                 }                             
  1122.                 case clearCommand:
  1123.                     TEDelete ( theTE );     
  1124.                     hasHandled = true;
  1125.                     break;
  1126.                                              
  1127.                 case selectAllCommand:
  1128.                     TESetSelect(0, kMaxTELength, theTE);
  1129.                     hasHandled = true;
  1130.                       break;
  1131.             }
  1132.                 
  1133.             break;
  1134.     }
  1135.     return hasHandled;
  1136. }
  1137.  
  1138. void MoveOneDialogItem ( DialogPtr theDialog,
  1139.                          short     theItem,
  1140.                          short     deltaW,
  1141.                          short     deltaH )
  1142. {
  1143.     short  theType;
  1144.     Handle theHandle;
  1145.     Rect   itemRect;
  1146.     
  1147.     GetDItem(theDialog, theItem, &theType, &theHandle, &itemRect);
  1148.     OffsetRect ( &itemRect, deltaW, deltaH);
  1149.     SetDItem(theDialog, theItem, theType, theHandle, &itemRect);
  1150. }
  1151.  
  1152. void MoveOneDialogControlItem( DialogPtr theDialog,
  1153.                                  short     theItem,
  1154.                                  short     deltaW,
  1155.                                  short     deltaH )
  1156. {
  1157.     short  theType;
  1158.     Handle theHandle;
  1159.     Rect   itemRect;
  1160.     
  1161.     GetDItem(theDialog, theItem, &theType, &theHandle, &itemRect);
  1162.     OffsetRect ( &itemRect, deltaW, deltaH);
  1163.     SetDItem(theDialog, theItem, theType, theHandle, &itemRect);
  1164.  
  1165.     MoveControl ( (ControlHandle)theHandle,
  1166.                     (**(ControlHandle)theHandle).contrlRect.left + deltaW,
  1167.                     (**(ControlHandle)theHandle).contrlRect.top  + deltaH);
  1168. }
  1169.  
  1170. void MoveScrollBarItem( DialogPtr theDialog,
  1171.                         short     theItem,
  1172.                         short     deltaW,
  1173.                         short     deltaH )
  1174. {
  1175.     short  theType;
  1176.     Handle theHandle;
  1177.     Rect   itemRect;
  1178.     Rect   controlRect;
  1179.     ControlHandle hTheControl;
  1180.     
  1181.     GetDItem(theDialog, theItem, &theType, &theHandle, &itemRect);
  1182.     
  1183.     itemRect.left  = itemRect.left + deltaW;
  1184.     itemRect.right = itemRect.right + deltaW;
  1185.     itemRect.bottom = itemRect.bottom + deltaH;
  1186.  
  1187.     SetDItem(theDialog, theItem, theType, theHandle, &itemRect);
  1188.  
  1189.     hTheControl = ((pStyleTextInfo) GetWRefCon(theDialog))->theScrollBar;
  1190.     controlRect = (**hTheControl).contrlRect;
  1191.     HideControl ( hTheControl );
  1192.     SizeControl ( hTheControl,
  1193.                     controlRect.right - controlRect.left,
  1194.                     deltaH + controlRect.bottom - controlRect.top );
  1195.     MoveControl ( hTheControl,
  1196.                     controlRect.left + deltaW,
  1197.                     controlRect.top );
  1198.     ShowControl ( hTheControl );
  1199. }
  1200.  
  1201. void MoveCustTextEditItem( DialogPtr theDialog,
  1202.                             short     theItem,
  1203.                             short     deltaW,
  1204.                             short     deltaH )
  1205. {
  1206.     short    theType;
  1207.     Handle   theHandle;
  1208.     Rect     itemRect;
  1209.     TEHandle theTEHandle;
  1210.     
  1211.     GetDItem(theDialog, theItem, &theType, &theHandle, &itemRect);
  1212.     
  1213.     itemRect.right = itemRect.right + deltaW;
  1214.     itemRect.bottom = itemRect.bottom + deltaH;
  1215.     SetDItem(theDialog, theItem, theType, theHandle, &itemRect);
  1216.  
  1217.     theTEHandle = ((pStyleTextInfo) GetWRefCon(theDialog))->theTEHandle;
  1218.     (**theTEHandle).destRect.right  = (**theTEHandle).destRect.right  + deltaW;
  1219.     (**theTEHandle).destRect.bottom = (**theTEHandle).destRect.bottom + deltaH;
  1220.     (**theTEHandle).viewRect.right  = (**theTEHandle).viewRect.right  + deltaW;
  1221.     (**theTEHandle).viewRect.bottom = (**theTEHandle).viewRect.bottom + deltaH;
  1222. }
  1223.  
  1224.  
  1225. pascal Boolean    MyFilterProc( DialogPtr theDialog, EventRecord *myEvent, short *itemHit )
  1226. {
  1227.     short            myPart;
  1228.     WindowPtr        whichWindow;
  1229.     TEHandle        newTE;
  1230.     Boolean            extend;
  1231.     GrafPtr            oldPort;
  1232.     Point            mousePt;
  1233.     char            myKey;
  1234.     Boolean            returnVal;
  1235.     long            menuResult;
  1236.     Rect            teItemRect;
  1237.     Rect            scrollItemRect;
  1238.     Rect            growItemRect;
  1239.     ControlHandle    newScroll;
  1240.     ControlHandle    theControl;
  1241.     short            part;
  1242.     short            value;
  1243.     short            cntlCode;
  1244.     Rect             growBounds;
  1245.     long             newRectSize;
  1246.     short             deltaW;
  1247.     short             deltaH;
  1248.     SFTypeList      myTypes = {'TEXT'};
  1249. #ifdef THINK_C
  1250.     ModalFilterUPP    standardProc;
  1251. #endif
  1252.     
  1253.     GetPort(&oldPort);
  1254.     
  1255.     returnVal = false;
  1256.     
  1257.     newTE     = ((pStyleTextInfo)GetWRefCon(theDialog))->theTEHandle;
  1258.     newScroll = ((pStyleTextInfo)GetWRefCon(theDialog))->theScrollBar;
  1259.     
  1260.     TEIdle(newTE);
  1261.     
  1262.     // Maintain the cursor
  1263.     
  1264.     SetPort(theDialog);
  1265.     GetMouse(&mousePt);
  1266.     
  1267.     GetRectOfDialogItem(theDialog, kTextItem,  &teItemRect);
  1268.     GetRectOfDialogItem(theDialog, kScrollBar, &scrollItemRect);
  1269.     GetRectOfDialogItem(theDialog, kGrowBox, &growItemRect);
  1270.     
  1271.     if (PtInRect(mousePt, &teItemRect))
  1272.     SetCursor(&editCursor);
  1273.     else
  1274.     SetCursor(&qd.arrow);
  1275.     
  1276.     switch (myEvent->what)
  1277.     {
  1278.         case mouseDown:
  1279.             myPart = FindWindow(myEvent->where, &whichWindow);
  1280.             
  1281.             if ( ( whichWindow != theDialog ) && ( myPart != inMenuBar ) )
  1282.                 break;
  1283.  
  1284.             switch (myPart)
  1285.             {
  1286.                 case inContent:
  1287.                 case inGrow:
  1288.                     SetPort(whichWindow);
  1289.                     mousePt = myEvent->where;
  1290.                     GlobalToLocal(&mousePt);
  1291.             
  1292.                     extend = ((myEvent->modifiers & shiftKey) != 0);
  1293.                     if ( PtInRect( mousePt, &(*(newTE))->viewRect ) )
  1294.                     {
  1295.                         TEClick(mousePt, extend, newTE);
  1296.                         TrackTEPosn(newScroll, newTE);
  1297.                     }
  1298.                     else
  1299.                     {
  1300.                         if (PtInRect(mousePt, &scrollItemRect))
  1301.                         {
  1302.                             cntlCode = FindControl(mousePt, theDialog, &theControl);
  1303.                             if (theControl)
  1304.                                 if (cntlCode == inThumb)
  1305.                                 {
  1306.                                     value = GetCtlValue(theControl);
  1307.                                     part  = TrackControl(theControl, mousePt, nil);
  1308.                                     if (part)
  1309.                                     {
  1310.                                         value -= GetCtlValue(theControl);
  1311.                                         if (value)
  1312.                                             TEScroll(0, value, newTE);
  1313.                                     }
  1314.                                 }
  1315.                                 else if ( cntlCode != 0 )
  1316.                                     part = TrackControl(theControl, mousePt, gScrollScriptVActionUPP);
  1317.                         }    // See if click is in grow box
  1318.                         else if ( PtInRect(mousePt, &growItemRect ))
  1319.                         {
  1320.         // Let the user drag out the new window size
  1321.                              SetRect(&growBounds, 300, 115,
  1322.                                                  qd.screenBits.bounds.right,
  1323.                                                  qd.screenBits.bounds.bottom);
  1324.                             newRectSize = GrowWindow ( whichWindow, myEvent->where,
  1325.                                                         &growBounds);
  1326.                             if (newRectSize)
  1327.                             {
  1328.         // Calculate the change in size of the window
  1329.                                 SetPort(theDialog);
  1330.                                 deltaW = LoWord(newRectSize) + whichWindow->portRect.left
  1331.                                             - whichWindow->portRect.right;
  1332.                                 deltaH = HiWord(newRectSize) + whichWindow->portRect.top
  1333.                                             - whichWindow->portRect.bottom;
  1334.                                 
  1335.         // Move all the items arround as appropriate
  1336.                                 MoveOneDialogControlItem( theDialog, ok,         deltaW, deltaH );
  1337.                                 MoveOneDialogControlItem( theDialog, cancel,     deltaW, deltaH );
  1338.                                 MoveOneDialogControlItem( theDialog, kCompile,   deltaW, deltaH );
  1339.                                 MoveOneDialogItem( theDialog, kGrowBox, deltaW, deltaH );
  1340.  
  1341.         // Move the scroll bar and Text edit around. Change the scroll bar's maximum
  1342.         //   and current value as necessary
  1343.                                 MoveScrollBarItem( theDialog, kScrollBar, deltaW, deltaH );
  1344.                                 MoveCustTextEditItem( theDialog, kTextItem, deltaW, deltaH );
  1345.                                 SetScrollLimit( newScroll, newTE);
  1346.  
  1347.         // Resize the window, don't bother about the update because we're going it
  1348.         //     invalidate it all later
  1349.                                 SizeWindow ( whichWindow,
  1350.                                              LoWord(newRectSize), HiWord(newRectSize),
  1351.                                              false );
  1352.  
  1353.         // Invalidate the window for update : Note that you have to add an erase rect
  1354.         //     to make sure that the window is cleared. This seems to be because the
  1355.         //     Dialog manager doesn't do one.
  1356.                 
  1357.                                 EraseRect( &whichWindow->portRect );
  1358.                                 InvalRect( &whichWindow->portRect );
  1359.                             }
  1360.                             returnVal = true;
  1361.                         }
  1362.                     }
  1363.                     break;
  1364.             
  1365.                 case inDrag:
  1366.                     DragWindow(whichWindow, myEvent->where, &qd.screenBits.bounds);
  1367.                     returnVal = true; // Stops modal dialog beeping
  1368.                     break;
  1369.             
  1370.                 case inMenuBar:
  1371.                     menuResult = MenuSelect(myEvent->where);
  1372.                     DoDialogMenu( menuResult, newTE );
  1373.                     HiliteMenu( 0 );
  1374.                     returnVal = true;   // Always return handled to stop beeping
  1375.                     break;                                                                                        
  1376.             }
  1377.             break;
  1378.  
  1379.         case keyDown:
  1380.         case autoKey: // Need hooks here for command keys if menus enabled
  1381.             myKey = myEvent->message & charCodeMask;
  1382.             
  1383.             if ((myEvent->modifiers & cmdKey) == cmdKey)
  1384.             {
  1385.                 menuResult = MenuKey(myKey);
  1386.                 returnVal = DoDialogMenu( menuResult, newTE );
  1387.                 HiliteMenu(0);
  1388.             }
  1389.             else if ( myKey != kEscapeKey ) // Escape Key
  1390.                 if ( myKey == kEndOfTextKey )
  1391.                 {
  1392.                     *itemHit = kCompile;
  1393.                     FlashButton(theDialog, kCompile);
  1394.                     returnVal = true;
  1395.                 }
  1396.                 else
  1397.                 {
  1398.                     TEKey(myKey, newTE);
  1399.                     SetScrollLimit(newScroll, newTE);
  1400.                     TrackTEPosn(newScroll, newTE);
  1401.                     returnVal = true;
  1402.                 }
  1403.             break;
  1404.                                 
  1405.         case activateEvt:
  1406.             if (((myEvent->modifiers & activeFlag) != 0))
  1407.             {
  1408.                 if ((WindowPtr)myEvent->message == theDialog)
  1409.                     TEActivate(newTE);
  1410.                 else
  1411.                     DoActivate((WindowPtr)myEvent->message, true); // Should not get here!
  1412.             }
  1413.             else if ((WindowPtr)myEvent->message == theDialog)
  1414.                 TEDeactivate(newTE);
  1415.             else
  1416.                 DoActivate((WindowPtr)myEvent->message, false);
  1417.             break;
  1418.                                         
  1419.         case updateEvt:
  1420.             if (Ours((WindowPtr)myEvent->message))
  1421.                 DoUpdate( (WindowPtr)myEvent->message );
  1422.             break;
  1423.     }
  1424.  
  1425.     if ( ! returnVal )
  1426.     {
  1427.         #ifdef THINK_C    // Can't use StdFilterProc() get and
  1428.                         //  call the standard filter ourselves
  1429.             if ( noErr == GetStdFilterProc( &standardProc ) ) 
  1430.                 returnVal= ((ModalFilterUPP)standardProc)( theDialog, myEvent, itemHit );
  1431.         #else
  1432.             returnVal = StdFilterProc( theDialog, myEvent, itemHit );
  1433.         #endif
  1434.     }
  1435.     
  1436.     MaintainEditItems( newTE, 1, myTypes );
  1437.     SetPort( oldPort );
  1438.     
  1439.     return returnVal;
  1440. }
  1441.  
  1442.  
  1443. // Given a resource ID for a menu, along with a OSAID for a script
  1444. //  to be associated with it. This routine sets the menu or menu item
  1445. //  script property. This in turn sets that the script has changed
  1446. //  so that it will get saved when the application is quit.
  1447.  
  1448. OSErr    SetMenuScript( short theResID, OSAID theScriptID )
  1449. {
  1450.     MenuPropToken        aMenuPropToken;
  1451.     MenuItemPropToken    aMenuItemPropToken;
  1452.     AEDesc                aDesc = { typeNull, NULL };
  1453.     OSErr                anErr;
  1454.               
  1455.     anErr = GetScriptDesc( theScriptID, typeWildCard, &aDesc );
  1456.  
  1457.     if ( theResID % 32 )    // Then the script is for an item
  1458.     {
  1459.         MenuItemTokenFromResID( theResID, &aMenuItemPropToken.token );
  1460.         aMenuItemPropToken.tokenProperty = pScript;
  1461.  
  1462.         anErr = SetMenuItemTokenProperty( &aMenuItemPropToken, &aDesc );
  1463.     }
  1464.     else                    // The script is for the whole menu
  1465.     {
  1466.         MenuTokenFromResID( theResID, &aMenuPropToken.token );
  1467.         aMenuPropToken.tokenProperty = pScript;
  1468.  
  1469.         anErr = SetMenuTokenProperty( &aMenuPropToken, &aDesc );
  1470.     }
  1471.     
  1472. done:
  1473.     (void)AEDisposeDesc( &aDesc );
  1474.  
  1475.     return anErr;
  1476. }
  1477.  
  1478. void SetMenuForDialog ( void )
  1479. {
  1480.     Boolean redrawMenuBar = false;
  1481.     
  1482. // Unhilite the menu bar
  1483.     HiliteMenu( 0 );
  1484.  
  1485. // Gray out apple menu (This will allow us to get at the edit menu)
  1486.     redrawMenuBar |= SetMenuItemState ( false, myMenus[appleM], kMenuTitle);
  1487.  
  1488. // Now Gray out everything apart from the edit menu
  1489.     redrawMenuBar |= SetMenuItemState ( false,  myMenus[fileM], kMenuTitle);
  1490.     if ( CountDocuments( ) > 0 )
  1491.     {
  1492.         redrawMenuBar |= SetMenuItemState ( false, myMenus[fontM], kMenuTitle);
  1493.         redrawMenuBar |= SetMenuItemState ( false, myMenus[sizeM], kMenuTitle);
  1494.         redrawMenuBar |= SetMenuItemState ( false, myMenus[styleM], kMenuTitle);
  1495.         redrawMenuBar |= SetMenuItemState ( false, myMenus[scriptM], kMenuTitle);
  1496.         redrawMenuBar |= SetMenuItemState ( false, myMenus[subroutineM], kMenuTitle);
  1497.     }
  1498.  
  1499. // Enable the edit menu
  1500.     redrawMenuBar |= SetMenuItemState ( true, myMenus[editM], kMenuTitle);
  1501.     SetMenuItemState ( true, myMenus[editM], cutCommand);
  1502.     SetMenuItemState ( true, myMenus[editM], copyCommand);
  1503.     SetMenuItemState ( true, myMenus[editM], pasteCommand);
  1504.     SetMenuItemState ( true, myMenus[editM], clearCommand);
  1505.     SetMenuItemState ( true, myMenus[editM], selectAllCommand);
  1506.  
  1507.     if (redrawMenuBar)
  1508.         DrawMenuBar();
  1509. }
  1510.  
  1511. void ReSetMenuForDialog ( void )
  1512. {
  1513.     Boolean redrawMenuBar = false;
  1514.     
  1515.         // Reset the menus
  1516.     redrawMenuBar |= SetMenuItemState ( true, myMenus[appleM], kMenuTitle);
  1517.     redrawMenuBar |= SetMenuItemState ( true, myMenus[fileM], kMenuTitle);
  1518.     if ( CountDocuments( ) > 0 )
  1519.     {
  1520.         redrawMenuBar |= SetMenuItemState ( true, myMenus[fontM], kMenuTitle);
  1521.         redrawMenuBar |= SetMenuItemState ( true, myMenus[sizeM], kMenuTitle);
  1522.         redrawMenuBar |= SetMenuItemState ( true, myMenus[styleM], kMenuTitle);
  1523.         redrawMenuBar |= SetMenuItemState ( true, myMenus[scriptM], kMenuTitle);
  1524.         redrawMenuBar |= SetMenuItemState ( true, myMenus[subroutineM], kMenuTitle);
  1525.     }
  1526.     MaintainMenus( &redrawMenuBar);
  1527. }
  1528.  
  1529.  
  1530. OSErr    EditMenuScript(short theMenu, short theItem)
  1531. {
  1532.     short         resID;
  1533.     OSAID         myScriptID;
  1534.     OSErr         myErr;
  1535.     OSErr         ignoreErr;
  1536.     AEDesc        scriptTextDesc;
  1537.     DialogPtr     scriptEditDlog;
  1538.     short         itemHit;
  1539.     TEHandle      newTE;
  1540.     GrafPtr       oldPort;
  1541.     Rect          itemRect;
  1542.     OSAID         myCompiledID;
  1543.     Boolean       wholeMenu;
  1544.     ControlHandle myScrollBar;
  1545.     StyleTextInfo theStyleTextInfo;
  1546.     ModalFilterUPP modalFilterDescriptor;
  1547.  
  1548.     SetMenuForDialog( );
  1549.  
  1550.     gEditingScript = true;
  1551.  
  1552.     GetPort(&oldPort);
  1553.     
  1554.     //    Look for a script associated with theItem first,
  1555.     //    and if not found look for one associated with 
  1556.     //    the whole menu
  1557.     
  1558.     wholeMenu = false;
  1559.     
  1560.     resID = ( theMenu << 5 ) + theItem;
  1561.     
  1562.     myScriptID = GetScriptIDForResID( resID );
  1563.     
  1564.     if ( myScriptID == kOSANullScript )
  1565.     {
  1566.         resID = (theMenu<<5);
  1567.         myScriptID = GetScriptIDForResID(resID);
  1568.         wholeMenu = true;
  1569.     }
  1570.             
  1571.     scriptEditDlog = GetNewDialog( MenuScriptEditor, NULL, (WindowPtr)-1 );                     
  1572.     SetPort( scriptEditDlog );
  1573.  
  1574.     //    Create a styled text edit record for the userItem
  1575.     //    and install it
  1576.  
  1577.     GetRectOfDialogItem( scriptEditDlog, kTextItem,  &itemRect );
  1578.     
  1579.     InsetRect(&itemRect, 5, 5);
  1580.     
  1581.     newTE = TEStylNew(&itemRect, &itemRect);
  1582.     
  1583.     TEAutoView(true, newTE);
  1584.     
  1585.     SetDrawProcForUserItem(scriptEditDlog, kTextItem, gDrawStyledTextUPP);
  1586.     
  1587.     //    Now create a scrollbar and install it
  1588.     
  1589.     GetRectOfDialogItem(scriptEditDlog, kScrollBar, &itemRect);
  1590.     
  1591.     myScrollBar = NewControl(scriptEditDlog, &itemRect, (unsigned char *)"",
  1592.                                 true, 0, 0, kMaxTELength, // Will be fixed up later - by SetScrollLimit()
  1593.                                  scrollBarProc, 0);
  1594.                                                      
  1595.     SetDrawProcForUserItem(scriptEditDlog, kScrollBar, gDrawScrollBarUPP);
  1596.  
  1597.     //    Now create grow box draw proc
  1598.     SetDrawProcForUserItem(scriptEditDlog, kGrowBox, gDrawGrowBoxUPP);
  1599.     
  1600.     //    Use the dialog window refcon to allow access to the 
  1601.     //    TEHandle and scrollHandle avoiding the use
  1602.     //    of globals
  1603.     
  1604.     theStyleTextInfo.theTEHandle  = newTE;
  1605.     theStyleTextInfo.theScrollBar = myScrollBar;
  1606.     
  1607.     SetWRefCon(scriptEditDlog, (long) &theStyleTextInfo);
  1608.  
  1609.     //    Put the source of the script into the 
  1610.     //    text edit record
  1611.     
  1612.     myErr = OSAGetSource(gScriptingComponent, myScriptID,
  1613.                                     typeStyledText, &scriptTextDesc);
  1614.  
  1615.     PutStyledTextFromDescIntoTEHandle(&scriptTextDesc, newTE);
  1616.     
  1617.     ignoreErr = AEDisposeDesc(&scriptTextDesc);
  1618.     
  1619.     SetScrollLimit(myScrollBar, newTE);
  1620.     TrackTEPosn(myScrollBar, newTE);
  1621.  
  1622.     // Set item 1 - <OK> to have a default box around it
  1623.     SetDialogDefaultItem(scriptEditDlog,ok);
  1624.     SetDialogCancelItem(scriptEditDlog,cancel);
  1625.     
  1626.     //    Added during PowerPC port:
  1627.     
  1628.     modalFilterDescriptor = NewModalFilterProc( MyFilterProc );
  1629.     
  1630.     do
  1631.     {
  1632.         ModalDialog(modalFilterDescriptor, &itemHit);
  1633.         switch ( itemHit )
  1634.         {
  1635.             case ok:
  1636.             case kCompile:
  1637.                 SetCursor(&waitCursor);
  1638.                 HLock((Handle)(**newTE).hText);
  1639.                 myErr = AECreateDesc(typeChar, (Ptr)*((**newTE).hText),
  1640.                                         (**newTE).teLength, &scriptTextDesc);
  1641.                 HUnlock((Handle)(**newTE).hText);
  1642.                                                 
  1643.                 myCompiledID = kOSANullScript;
  1644.                 myErr = OSACompile(gScriptingComponent, &scriptTextDesc,
  1645.                                             kOSAModeCompileIntoContext, &myCompiledID);
  1646.                                                                                      
  1647.                 ignoreErr = AEDisposeDesc(&scriptTextDesc);
  1648.                                                 
  1649.                 scriptTextDesc.dataHandle = nil;
  1650.                                                 
  1651.                 if (myErr==noErr)
  1652.                 {
  1653.                     myErr = OSAGetSource(gScriptingComponent, myCompiledID,
  1654.                                                     typeStyledText, &scriptTextDesc);
  1655.                                                              
  1656.                         // Zap current contents and replace with returned source
  1657.                          
  1658.                     TESetSelect(0, kMaxTELength, newTE);
  1659.                     TEDelete(newTE);
  1660.  
  1661.                          // We deleted all the text so it won't be scrolled anymore
  1662.                     SetCtlValue(myScrollBar, 0);
  1663.                     
  1664.                     PutStyledTextFromDescIntoTEHandle(&scriptTextDesc, newTE);
  1665.                     
  1666.                     DrawStyledTextEditRec(scriptEditDlog, kTextItem);
  1667.                                                          
  1668.                     ignoreErr = AEDisposeDesc(&scriptTextDesc);
  1669.                 }
  1670.                 else if ( errOSAScriptError == myErr )
  1671.                 {
  1672.                     DisplayErrorInScript( newTE );
  1673.                     itemHit  = 0; // Stop dialog going away
  1674.                 }
  1675.                     
  1676.                 SetScrollLimit(myScrollBar, newTE);
  1677.                 TrackTEPosn(myScrollBar, newTE);
  1678.             
  1679.                 SetCursor(&qd.arrow);
  1680.                     
  1681.                 if ( ok == itemHit )
  1682.                 {        // Swap this script for the old one even if whole menu 
  1683.                     if ( noErr == myErr )
  1684.                         SetMenuScript( resID, myCompiledID );
  1685.                     else
  1686.                         itemHit = -1;
  1687.                 }
  1688.                                                         
  1689.                 (void)OSADispose(gScriptingComponent, myCompiledID);
  1690.                 break;
  1691.                                                 
  1692.             case cancel: 
  1693.             case kTextItem: 
  1694.             case kScrollBar:
  1695.                 break;
  1696.         }
  1697.     } while ( itemHit != ok && itemHit != cancel );
  1698.             
  1699.     DisposeRoutineDescriptor( modalFilterDescriptor );
  1700.             
  1701.     DisposeDialog( scriptEditDlog );
  1702.     
  1703.     SetPort(oldPort);
  1704.  
  1705.     gEditingScript = false;
  1706.  
  1707.     ReSetMenuForDialog( );
  1708.     
  1709.     return noErr;
  1710. }
  1711.  
  1712.  
  1713. OSAError    LoadDocumentScript( DPtr theDoc, short theFileRef )
  1714. {
  1715.     OSAError    err;
  1716.  
  1717.     theDoc->theScriptID = kOSANullScript;
  1718.     
  1719.     err = LoadScriptFromResFileRef( theFileRef,
  1720.                     kDefaultDocumentScript, &theDoc->theScriptID );
  1721.                     
  1722.     return err;
  1723. }
  1724.  
  1725.  
  1726. OSAError    StoreDocumentScript( DPtr theDoc, short theFileRef )
  1727. {
  1728.     OSAError    err;
  1729.     
  1730.     if ( kOSANullScript == theDoc->theScriptID )
  1731.         return noErr;
  1732.     
  1733.     err = StoreScriptToResFileRef( theFileRef, kDefaultDocumentScript,
  1734.                                 theDoc->theScriptID, "\pDocument Script" );
  1735.                     
  1736.     return err;
  1737. }
  1738.  
  1739.  
  1740. OSAError    GetScriptProperty( OSAID contextID, const AEDesc* propertyName, AEDesc* result )
  1741. {
  1742.     OSAID        aScriptValueID = kOSANullScript;
  1743.     OSAError    err;
  1744.     
  1745.     if ( kOSANullScript == contextID )
  1746.         return errAEEventNotHandled;
  1747.     
  1748.                         // Get the property as a script ID
  1749.     err = OSAGetProperty( gScriptingComponent, kOSAModeNull, contextID,
  1750.                                         propertyName, &aScriptValueID );
  1751.     if (noErr != err) goto done;
  1752.                         // Convert the script data located by the script ID to an AEDesc
  1753.     err = OSACoerceToDesc( gScriptingComponent, aScriptValueID,
  1754.                                     typeWildCard, kOSAModeNull, result );
  1755.  
  1756. done:
  1757.     (void)OSADispose( gScriptingComponent, aScriptValueID );
  1758.  
  1759.     return(err);
  1760. }
  1761.  
  1762.  
  1763. // Set a script property using a descriptor.
  1764.  
  1765. OSAError    SetScriptProperty( OSAID contextID, const AEDesc* propertyName, const AEDesc* value )
  1766. {
  1767.     OSAID        aScriptValueID = kOSANullScript;
  1768.     OSAError    err;
  1769.                         // Convert from a descriptor to a script ID
  1770.     err = OSACoerceFromDesc( gScriptingComponent, value,
  1771.                                        kOSAModeNull, &aScriptValueID );
  1772.     if (noErr != err) goto done;
  1773.                         // Set the property using the script ID
  1774.     err = OSASetProperty( gScriptingComponent, kOSAModeNull,
  1775.                                 contextID, propertyName, aScriptValueID );
  1776.  
  1777. done:
  1778.     (void)OSADispose( gScriptingComponent, aScriptValueID );
  1779.  
  1780.     return(err);
  1781. }
  1782.  
  1783.  
  1784. OSErr    GetScriptDesc( OSAID theScriptID, DescType theWantType, AEDesc* theResult )
  1785. {
  1786.     OSErr    err;
  1787.  
  1788.     if ( theWantType == typeChar || theWantType == typeIntlText )
  1789.     {    // If caller wants text, we need to de-compile the script
  1790.         err = (OSErr)OSAGetSource( gScriptingComponent, theScriptID, 
  1791.                                                         theWantType, theResult );
  1792.     }
  1793.     else
  1794.     {
  1795.         if ( theWantType == typeWildCard )
  1796.             theWantType = typeOSAGenericStorage;
  1797.             
  1798.         err = (OSErr)OSAStore( gScriptingComponent, theScriptID, 
  1799.                                 theWantType, kOSAModeDontStoreParent, theResult );
  1800.     }
  1801.     
  1802.     return err;
  1803. }
  1804.  
  1805.  
  1806. OSErr    SetScriptDesc( const AEDesc* theData, OSAID* theResult )
  1807. {
  1808.     OSAID         aScriptID = kOSANullScript;
  1809.     OSAError    err;
  1810.  
  1811.     switch ( theData->descriptorType )
  1812.     {
  1813.         case typeChar:
  1814.         case typeIntlText:
  1815.             err = OSACompile( gScriptingComponent, theData, 
  1816.                                      kOSAModeCompileIntoContext, &aScriptID );
  1817.             if ( errOSAScriptError == err )
  1818.                 DisplayOSAScriptError( NULL );
  1819.             break;
  1820.         
  1821.         default:
  1822.             err = OSALoad( gScriptingComponent, theData, 
  1823.                                     kOSAModeNull, &aScriptID );
  1824.     }
  1825.     
  1826.     if ( noErr == err )
  1827.     {
  1828.         (void)OSADispose( gScriptingComponent, *theResult );
  1829.         *theResult = aScriptID;
  1830.     }
  1831.  
  1832.     return (OSErr)err;
  1833. }
  1834.  
  1835. void    AddMissingParameter( AEKeyword theAEKeyword, DescType theType,
  1836.                                     Ptr theData, Size theDataSize, AppleEvent* theEvent )
  1837. {
  1838.     AEDesc    aDesc = { typeNull, NULL };
  1839.     OSErr    anErr;
  1840.     
  1841.         // See if the parameter is there first
  1842.     anErr = AEGetParamDesc( theEvent, theAEKeyword, typeWildCard, &aDesc );
  1843.     if ( noErr == anErr ) goto done;
  1844.     
  1845.     switch ( theType )
  1846.     {
  1847.         case typeAEList:
  1848.         case typeAERecord:
  1849.             anErr = AECreateList( NULL, 0, ( typeAERecord == theType ), &aDesc );
  1850.             if ( noErr != anErr ) goto done;
  1851.         
  1852.             anErr = AEPutParamDesc( theEvent, theAEKeyword, &aDesc );
  1853.             break;
  1854.             
  1855.         default:
  1856.             anErr = AECreateDesc( theType, theData, theDataSize, &aDesc );
  1857.             if ( noErr != anErr ) goto done;
  1858.         
  1859.             anErr = AEPutParamDesc( theEvent, theAEKeyword, &aDesc );
  1860.     }
  1861.  
  1862. done:    
  1863.     (void)AEDisposeDesc( &aDesc );
  1864. }
  1865.  
  1866.  
  1867. Boolean    CanScriptEvent( AEEventClass theClass, AEEventID theID, AppleEvent* theEvent )
  1868. {
  1869.     DescType    aType;
  1870.     FSSpec        aSpec;
  1871.     Boolean        result;
  1872.     
  1873.     switch ( theClass )
  1874.     {
  1875.         case kCoreEventClass:
  1876.             switch ( theID )
  1877.             {
  1878.                 case kAEOpenApplication:
  1879.                     result = false;
  1880.                     break;
  1881.                     
  1882.                 default:
  1883.                     result = true;
  1884.             }
  1885.             break;
  1886.             
  1887.         case kAECoreSuite:
  1888.             switch ( theID )
  1889.             {
  1890.                 case kAESetData:
  1891.                 case kAEGetData:
  1892.                 case kAEDoObjectsExist:
  1893.                     result = false;
  1894.                     break;
  1895.                     
  1896.                 case kAECreateElement:
  1897.                     aType = typeNull;     // Null to show nothing
  1898.                     AddMissingParameter( keyAEInsertHere, typeType,
  1899.                                             (Ptr)&aType, sizeof( aType ), theEvent );
  1900.                     AddMissingParameter( keyAEData, typeAERecord, NULL, 0, theEvent );
  1901.                     AddMissingParameter( keyAEPropData, typeAERecord, NULL, 0, theEvent );
  1902.                     result = true;
  1903.                     break;
  1904.                     
  1905.                 case kAEClose:
  1906.                     aType = kAEAsk;     // Default for no parameter
  1907.                     AddMissingParameter( keyAESaveOptions, typeEnumeration,
  1908.                                             (Ptr)&aType, sizeof( aType ), theEvent );
  1909.                     result = true;
  1910.                     break;
  1911.                     
  1912.                 case kAESave:
  1913.                     aSpec.vRefNum = 0;    // Send a blank FSSpec
  1914.                     aSpec.parID = 0;
  1915.                     aSpec.name[0] = 0;
  1916.                     AddMissingParameter( keyAEFile, typeFSS,
  1917.                                             (Ptr)&aSpec, sizeof( aSpec ), theEvent );
  1918.                     result = true;
  1919.                     break;
  1920.                     
  1921.                 default:
  1922.                     result = true;
  1923.             }
  1924.             break;
  1925.  
  1926.         case kAEMiscStandards:    // e.g. kAERevert
  1927.             switch ( theID )
  1928.             {
  1929.                 default:
  1930.                     result = true;
  1931.             }
  1932.             break;
  1933.  
  1934.         case kASAppleScriptSuite:
  1935.             switch ( theID )
  1936.             {
  1937.                 case kASSubroutineEvent:
  1938.                     result = true;
  1939.                     break;
  1940.                     
  1941.                 default:
  1942.                     result = false;
  1943.             }
  1944.             break;
  1945.             
  1946.         default:
  1947.             result = false;
  1948.     }
  1949.     
  1950.     return result;
  1951. }
  1952.  
  1953.  
  1954. // Debugging routine
  1955.  
  1956. OSAError    GetAHandler( AEDesc* theName, OSAID theOSAID );
  1957. OSAError    GetAHandler( AEDesc* theName, OSAID theOSAID )
  1958. {
  1959.     AEDesc        aDesc = { typeNull, NULL };
  1960.     OSAID        aResultID;
  1961.     OSAError    anErr;
  1962.  
  1963.     (void)DisplayDescResult( GetResultsWindPtr( ), theName, NULL, noErr );
  1964.     
  1965.     anErr = OSAGetHandler( gScriptingComponent, kOSAModeNull, theOSAID, theName, &aResultID );
  1966.     if ( noErr != anErr ) goto done;
  1967.     
  1968.     anErr = OSAGetSource( gScriptingComponent, aResultID, typeStyledText, &aDesc );
  1969.     if ( noErr != anErr ) goto done;
  1970.  
  1971. done:
  1972.     (void)DisplayDescResult( GetResultsWindPtr( ), &aDesc, NULL, anErr );
  1973.     (void)AEDisposeDesc( &aDesc );
  1974.  
  1975.     return anErr;
  1976. }
  1977.  
  1978. // Debugging routine
  1979.  
  1980. OSErr    LookAtHandlers( OSAID theOSAID );
  1981. OSErr    LookAtHandlers( OSAID theOSAID )
  1982. {
  1983.     AEDesc        aList = { typeNull, NULL },
  1984.                 aDesc = { typeNull, NULL };
  1985.     long        aCount,
  1986.                 anIndex;
  1987.     AEKeyword    anAEKeyword;
  1988.     OSAError    anErr;
  1989.  
  1990.     anErr = OSAGetHandlerNames( gScriptingComponent, kOSAModeNull, theOSAID, &aList );
  1991.     if ( noErr != anErr ) goto done;
  1992.     
  1993.     anErr = AECountItems( &aList, &aCount );
  1994.     if ( noErr != anErr ) goto done;
  1995.  
  1996.     for ( anIndex = 1; anIndex <= aCount; anIndex++ )
  1997.     {
  1998.         anErr = AEGetNthDesc( &aList, anIndex, typeWildCard, &anAEKeyword, &aDesc );
  1999.         if ( noErr != anErr ) continue;
  2000.         
  2001.         anErr = GetAHandler( &aDesc, theOSAID );
  2002.     }
  2003.  
  2004. done:
  2005.     (void)DisplayDescResult( GetResultsWindPtr( ) , &aDesc, NULL, anErr );
  2006.     (void)AEDisposeDesc( &aList );
  2007.     (void)AEDisposeDesc( &aDesc );
  2008.  
  2009.     return anErr;
  2010. }
  2011.  
  2012.  
  2013. static OSErr    GetTokenDescScript( AEDesc* theTokenDesc, OSAID* theOSAID )
  2014. {
  2015.     WindowToken        aWindowToken;
  2016.     Size            aSize;
  2017.     DPtr            aDoc;
  2018.     OSErr            err = noErr;
  2019.     
  2020.     *theOSAID = kOSANullScript;        // Null to begin with
  2021.  
  2022.     switch ( theTokenDesc->descriptorType )
  2023.     {
  2024.         case typeMyDocument:
  2025.             GetRawDataFromDescriptor( theTokenDesc, (Ptr)&aWindowToken,
  2026.                                                 sizeof( aWindowToken ), &aSize );
  2027.             aDoc = DPtrFromWindowPtr( aWindowToken.tokenWindow );
  2028.             *theOSAID = aDoc->theScriptID;
  2029.             
  2030. //            LookAtHandlers( *theOSAID );
  2031.             break;
  2032.             
  2033.         case typeMyAppl:
  2034.             *theOSAID = gAppRec.theScriptID;
  2035.  
  2036. //            LookAtHandlers( *theOSAID );
  2037.             break;
  2038.             
  2039.         default:
  2040.             err = errAEEventNotHandled;
  2041.     }
  2042.  
  2043.     return err;
  2044. }
  2045.  
  2046.  
  2047. OSErr    DoScriptEvent( AppleEvent            *theEvent, 
  2048.                         AppleEvent            *theReply, 
  2049.                         OSAID                theScriptID )
  2050. {
  2051.     OSAError            err = errAEEventNotHandled;
  2052.     AEEventHandlerUPP    oldResumeProc;
  2053.     long                oldRefcon;
  2054.     
  2055.     if ( kOSANullScript == theScriptID )
  2056.         return err;
  2057.     
  2058.     OSAGetResumeDispatchProc( gScriptingComponent, &oldResumeProc, &oldRefcon );
  2059.     
  2060.     err = OSASetResumeDispatchProc( gScriptingComponent,
  2061.                     (AEEventHandlerUPP)kOSAUseStandardDispatch, kOSADontUsePhac );
  2062.     if ( noErr == err )
  2063.     {
  2064.         err = OSADoEvent( gScriptingComponent, theEvent, theScriptID, 
  2065.                                                  kOSAModeAlwaysInteract, theReply );
  2066.         if ( errOSAScriptError == err )
  2067.             (void)DisplayOSAScriptError( NULL );
  2068.     }
  2069.  
  2070.     OSASetResumeDispatchProc( gScriptingComponent, oldResumeProc, oldRefcon ) ;
  2071.     
  2072.     return    (OSErr)err;
  2073. }
  2074.  
  2075.  
  2076. pascal OSErr    EventPrehandler( AppleEvent *theEvent, AppleEvent *theReply, long theRefcon )
  2077. {
  2078. #ifdef __MWERKS__
  2079.     #pragma unused( theRefcon )
  2080. #endif
  2081.  
  2082.     AEEventClass         aClass;
  2083.     AEEventID             anID;
  2084.     DescType            aType;
  2085.     Size                aSize;
  2086.     AEDesc                anObject = { typeNull, NULL },
  2087.                         aTokenDesc = { typeNull, NULL };
  2088.     OSAID                 aScriptID = kOSANullScript;
  2089.     OSAError             err;
  2090.  
  2091.     // Extract the class and ID of the event from the AppleEvent
  2092.     err = AEGetAttributePtr( theEvent, keyEventClassAttr, typeType,
  2093.                                     &aType, (Ptr)&aClass, sizeof( aClass ), &aSize ); 
  2094.     if ( noErr != err ) goto done;
  2095.  
  2096.     err = AEGetAttributePtr( theEvent, keyEventIDAttr, typeType,
  2097.                                     &aType, (Ptr)&anID, sizeof( anID ), &aSize );
  2098.     if ( noErr != err ) goto done;
  2099.     
  2100.     if ( CanScriptEvent( aClass, anID, theEvent ) )
  2101.     {        // Above test is to make sure we handle all the scriptable events 
  2102.             //  and that we skip the ones we don't want to be scriptable.
  2103.         err = AEGetParamDesc( theEvent, keyDirectObject, typeWildCard, &anObject );
  2104.  
  2105.             // If there is no object specifier for the direct object
  2106.             //  then well have a go with the application script.
  2107.         if ( noErr != err || typeObjectSpecifier != anObject.descriptorType )
  2108.             aTokenDesc.descriptorType = typeMyAppl;
  2109.         else
  2110.         {    // Resolve to an internal token
  2111.             err = AEResolve( &anObject, kAEIDoMinimum, &aTokenDesc );
  2112.             if ( noErr != err ) goto done;
  2113.         }
  2114.     
  2115.         err = GetTokenDescScript( &aTokenDesc, &aScriptID );
  2116.         if ( noErr != err ) goto done;
  2117.         
  2118.             // If there's no script then we want the application
  2119.             //  to handle it in the normal way.
  2120.         if ( kOSANullScript == aScriptID )
  2121.         {
  2122.             err = errAEEventNotHandled;
  2123.             goto done;
  2124.         }
  2125.         
  2126.         err = DoScriptEvent( theEvent, theReply, aScriptID );
  2127.     }
  2128.     else
  2129.         err = errAEEventNotHandled;
  2130.  
  2131. done:
  2132.     (void)AEDisposeDesc( &anObject );
  2133.     (void)AEDisposeDesc( &aTokenDesc );
  2134.         
  2135.     return (OSErr)err;
  2136. }
  2137.